iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0
Modern Web

擁抱 .Net Core系列 第 16

[Day16] .Net Core 中的Log - 2

  • 分享至 

  • xImage
  •  

我們昨天提到了原生的一些log機制,今天來看看.Net Core中的log 機制是如何使用及原理吧

Event

我們昨天有提到
通常一個log事件可以拆分為

  • 事件Id
  • 事件類型(事件等級)
  • 訊息

在dotnet core 中代表這三個東西的物件分別為

  • EventId
  • LogLevel
  • LoggerMessage

EventId

EventId.cs

public readonly struct EventId
{
    public static implicit operator EventId(int i)
    {
        return new EventId(i);
    }

    public static bool operator ==(EventId left, EventId right)
    {
        return left.Equals(right);
    }

    public static bool operator !=(EventId left, EventId right)
    {
        return !left.Equals(right);
    }

    public EventId(int id, string? name = null)
    {
        Id = id;
        Name = name;
    }

    public int Id { get; }

    public string? Name { get; }

    public override string ToString()
    {
        return Name ?? Id.ToString();
    }
    public bool Equals(EventId other)
    {
        return Id == other.Id;
    }

    public override bool Equals([NotNullWhen(true)] object? obj)
    {
        if (obj is null)
        {
            return false;
        }

        return obj is EventId eventId && Equals(eventId);
    }

    public override int GetHashCode()
    {
        return Id;
    }
}

可以看見EventId 本身為record struct 類型
意即本身是不可變的(immutable)
且額外做了隱含轉換,可以將事件Id轉成事件本身表示

var eventId = new EventId(1);
const int id = 1;

// True
Console.WriteLine(eventId == id);

LogLevel

LogLevel.cs

public enum LogLevel
{
    Trace = 0,
    Debug = 1,
    Information = 2,
    Warning = 3,
    Error = 4,
    Critical = 5,
    None = 6,
}

log的等級大致上可以分成7種
Critical為最嚴重,Trace 為最輕微
None我還真的不知道他要幹嘛用

下面是微軟官方對各等級的介紹

LogLevel 方法 描述
Trace 0 LogTrace 包含最詳細的訊息。 這些訊息可能包含敏感性應用程式資料。 這些訊息預設會停用,且不應在生產環境中啟用。
Debug 1 LogDebug 用於偵錯和開發。 由於大量,因此在生產環境中請謹慎使用。
Information 2 LogInformation 追蹤一般應用程式流程。 可能具有長期值。
Warning 3 LogWarning 針對異常或意外事件。 通常包含不會導致應用程式失敗的錯誤或狀況。
Error 4 LogError 發生無法處理的錯誤和例外狀況。 這些訊息指出目前作業或要求中發生失敗,而不是整個應用程式的失敗。
Critical 5 LogCritical 發生需要立即注意的失敗。 範例:資料遺失情況、磁碟空間不足。
None 6 指定不應該寫入任何訊息。

LoggerMessage

等等回頭看,我們先說說dotnet core中怎麼使用log

.Net Core 中的Log

.Net Core 中log的核心物件有3個

  • ILogger
  • ILoggerFactory
  • ILoggerProvider

在細講log的組成前,先來看看怎麼用

var logger = new ServiceCollection()
    // add log and configuration console providers
    .AddLogging(builder => builder.AddConsole())
    .BuildServiceProvider()
    .GetRequiredService<ILogger<Program>>();

var errorMessage = "This is an error message";

logger.Log(LogLevel.Information, "info");
logger.Log(LogLevel.Error, "error with compiled time constant message: {ErrorMessage}", errorMessage);
logger.Log(LogLevel.Critical, $"error with message: {errorMessage}");
logger.LogWarning("warning with message: {0}", errorMessage);

https://ithelp.ithome.com.tw/upload/images/20220927/20109549xMP4weHxPE.png

透過在 AddLogging() 做Log的初始化設定
builder.AddConsole() 表示 要新增一個輸出log到 Console 的 ILoggerProvier

至於ILogger 的用法主要有兩種

  • logger.Log(LogLevel, msg)
  • logger.LogWarning(msg)
    基本上兩種其實都一樣,後者的實作其實也是呼叫前者
    logger.Log(LogLevel.Warning, msg)
    但語意較清楚,要使用哪種就見仁見智

另外可以看到我在 Error, Critical, Warning 的message 中動了點手腳
Crital 的地方是透過字串插補的方式去寫入
而Error跟Wraning的地方則是比較像是string.Format的方式
這個跟前面跳過的LoggerMessage有點關係。

AddLogging

LoggingServiceCollectionExtensions.cs

services.TryAdd(ServiceDescriptor.Singleton<ILoggerFactory, LoggerFactory>());
services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(Logger<>)));

// log過濾設定
services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<LoggerFilterOptions>>(
    new DefaultLoggerLevelConfigureOptions(LogLevel.Information)));
}

AddLogging()的方法中比較重要的是這三行
註冊了 ILoggerFactoryILogger

另外設定了Default的Filter 來過濾最低LogLevelLogLevel.Information

我們也可以透過SetMinimumLevel(LogLevel)來設定最低log層級

var logger = new ServiceCollection()
    .AddLogging(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Error))

ILoggerProvider

我們的老朋友Provider 又來了,好像每一章都有他的存在
我們在紀錄log的時候,都是因為有必要才記,既然記了
勢必要有地方輸出log,不論是檔案,DB,MQ,或是螢幕
而實際上輸出這些log的東西就是ILoggerProvider

public interface ILoggerProvider : IDisposable
{
    ILogger CreateLogger(string categoryName);
}

Category 表示事件(log)的來源來自誰,是由誰寫入的,通常是類別,或是元件 或 service
我們前面在注入 ILogger<Program> 的時候
實際上會建立一個categrayName 為 ProgramILogger
透過強型別去避免輸入錯誤

閒聊

今天身體不大舒服/images/emoticon/emoticon06.gif,把ILoggerILoggerFactoryLoggerMessage 放在明天一起講


上一篇
[Day15] Log - 1
下一篇
[Day17] .Net Core 中的Log - 3
系列文
擁抱 .Net Core30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言